

<!DOCTYPE html>
<html lang="zh" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/walker_sue/img/favicon.png">
  <link rel="icon" type="image/png" href="/walker_sue/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="lk">
  <meta name="keywords" content="">
  <title>因子分解机, libFM与基于邻域的协同过滤 - Walker_Sue</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/walker_sue/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/github-gist.min.css" />
    
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/walker_sue/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/walker_sue/js/utils.js" ></script>
  <script  src="/walker_sue/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.3.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/walker_sue/">&nbsp;<strong>Walker</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/">
                <i class="iconfont icon-home-fill"></i>
                主页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                文档
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    主题博客
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/guide/">
                    
                    配置指南
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    图标用法
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/walker_sue/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container page-header text-center fade-in-up">
    <span class="h2" id="subtitle">
    
</span>




<div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-07-23 10:11" pubdate>
        July 23, 2021 am
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      5.9k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      67
       分钟
    </span>
  

  
  
</div>


</div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto" id="post">
            <!-- SEO header -->
            <h1 style="display: none">因子分解机, libFM与基于邻域的协同过滤</h1>
            
            <div class="markdown-body" id="post-body">
              <div align='center' ><font size='10'>机器学习-BI</font></div>


<hr>
<div align='center' ><font size='5'>Week_20</font></div>
<div align='center' ><font size='5'>因子分解机, libFM与基于邻域的协同过滤</font></div>

<hr>
<h3 id="CTR是个啥？"><a href="#CTR是个啥？" class="headerlink" title="CTR是个啥？"></a>CTR是个啥？</h3><p>点击率(click-through rate,CTR)是点击特定链接的用户与查看页面，电子邮件或广告的用户数量之比。它通常用于衡量某个网站的在线广告活动是否成功，以及电子邮件活动的有效性，是互联网公司进行流量分配的核心依据之一。  </p>
<p>$$CTR = \frac{number ofclick-throughs}{number of impressions} * 100% $$</p>
<p>无论使用什么类型的模型，点击率这个命题可以被归纳到二元分类的问题，我们通过单个个体的特征，计算出对于某个内容，是否点击了，点击了就是1，没点击就是0。对于任何二元分类的问题，最后我们都可以归结到逻辑回归上面。</p>
<ul>
<li>  早期的人工特征工程+LR（Logistic Regression）：这个方式需要大量的人工处理，不仅需要对业务和行业有所了解，对于算法的经验要求也十分的高。</li>
<li>  GBDT（Gradient Boosting Decision Tree）+LR：提升树短时这方面的第二个里程碑，虽然也需要大量的人工处理，但是由于其可解释性和提升树对于假例的权重提升，使得计算准确度有了很大的提高。</li>
<li>  FM-FFM：FM和FFM模型是最近几年提出的模型，并且在近年来表现突出，分别在由Criteo和Avazu举办的CTR预测竞赛中夺得冠军，使得到目前为止，还都是以此为主的主要模型占据主导位置。</li>
<li>  Embedding模型可以理解为FFM的一个变体。</li>
</ul>
<p>CTR预估技术从传统的Logistic回归，到近两年大火的深度学习，新的算法层出不穷：DeepFM, NFM, DIN, AFM, DCN等。其实这些算法都是特征工程方面的模型，无论最后怎么计算，最后一层都是一个二元分类的函数（sigmod为主）。本文主要涉及三种FM系列算法：FM，FFM，DeepFM。</p>
<h3 id="1-FM（Factorization-Machines，因子分解机）"><a href="#1-FM（Factorization-Machines，因子分解机）" class="headerlink" title="1.FM（Factorization Machines，因子分解机）"></a>1.FM（Factorization Machines，因子分解机）</h3><p>FM（Factorization Machines，因子分解机）最早由Steffen Rendle于2010年在ICDM上提出，它是一种通用的预测方法，在即使数据非常稀疏的情况下，依然能估计出可靠的参数进行预测。与传统的简单线性模型不同的是，因子分解机考虑了特征间的交叉，对所有的嵌套变量交互进行建模（类似于SVM中的核函数）和转化率CVR（conversion rate）两项指标上有着良好的表现。此外，FM的模型还具有可以用线性时间来计算，以及能够与许多先进的协同过滤方法（如Bias MF、SVD++等）相融合等优点。</p>
<p>在介绍FM模型之前，来看看稀疏数据的训练问题。以及广告CTR（click-through rate）点击率预测任务为例，假设有如下数据：<br><img src="20201210200424755.png" srcset="/walker_sue/img/loading.gif"></p>
<p>第一列Clicked是类别标记，标记用户是否点击了该广告，而其余列则是特征（这里的三个特征都是类别类型），一般的，我们会对数据进行One-hot编码将类别特征转化为数值特征，转化后数据如下：<br><img src="20201210200616408.png" srcset="/walker_sue/img/loading.gif"></p>
<p>经过One-hot编码后，特征空间是十分稀疏的。特别的，某类别特征有m种不同的取值，则One-hot编码后就会变为m维，当类别特征越多、类别特征的取值越多，其特征空间就更加稀疏。</p>
<p>同时通过观察大量的样本数据可以发现，某些特征经过关联之后，与label之间的相关性就会提高。例如，“USA”与“Thanksgiving”、“China”与“Chinese New Year”这样的关联特征，对用户的点击有着正向的影响。换句话说，来自“China”的用户很可能会在“Chinese New Year”有大量的浏览、购买行为，而在“Thanksgiving”缺不会有特别的消费行为。这种关联特征与label的正向相关性在实际问题中是普遍存在的，如“化妆品”类商品与“女性”，“球类运动配件”的商品与“男”性，“电影票”的商品与“电影”品类偏好等。因此，引入两个特征的组合是非常有意义的。</p>
<p>如何表示两个特征的组合呢？一种直接的办法就是采用多项式模型来表示两个特征的组合， $x_i$为第i个特征的取值， $x_ix_j$表示特征$x_i$和 $x_j$的特征组合，其系数w_{ij}即为我们学习的参数，也是$x_ix_j$组合的重要程度：<br>$$hat{y}(x)=w_0+\sum_{i=1}^dw_ix_i+\sum_{i=1}^d\sum_{j=i+1}^dw_{ij}x_ix_j$$</p>
<p>上式也可以称为Poly2（degree-2 poly-nomial mappings）模型。注意到式中参数的个数是非常多的，一次项有d+1个，二次项共有$\frac{d(d-1)}{2}$个，而参数与参数之间彼此独立，在稀疏场景下，二次项的训练是很困难的。因为要训练$w_{ij}$，需要有大量的 $x_i$和 $x_j$ 都非零的样本（只有非零组合才有意义）。而样本本身是稀疏的，满足$x_ix_j \ne 0$的样本会非常少，样本少则难以估计参数$w_{ij}$，训练出来容易导致模型的过拟合。</p>
<p>为此，Rendle与2010年提出FM模型，它能很好的求解上式，其特点如下：</p>
<ul>
<li>  FM模型可以在非常稀疏的情况下进行参数估计。</li>
<li>  FM模型是线性时间复杂度的，可以直接使用原问题进行求解，而且不像SVM一样依赖支持向量 。</li>
<li>  FM模型是一个通用的模型，其训练数据的特征取值可以是任意实数。而其它最先进的分解模型对输入数据有严格的限制。FMs可以模拟MF、SVD++、PITF或FPMC模型。</li>
</ul>
<h4 id="1-1FM模型原理"><a href="#1-1FM模型原理" class="headerlink" title="1.1FM模型原理"></a>1.1FM模型原理</h4><p>前面提到过，式中的参数难以训练是因为训练数据的稀疏性。对于不同的特征对 $x_i$,$x_j$和$x_i$,$x_k$,认为是完全独立的，对参数 $w_{ij}$和$w_{ik}$分别进行训练。而实际上并非如此，不同特征之间进行组合并非完全独立，如下图所示：<br><img src="20201210203334601.png" srcset="/walker_sue/img/loading.gif"></p>
<p>回想<a target="_blank" rel="noopener" href="https://blog.csdn.net/wei$x_i$n_43849871/article/details/110286087">矩阵分解</a>，一个rating可以分解为user矩阵和item矩阵，如下图所示：<br><img src="20201210203605700.png" srcset="/walker_sue/img/loading.gif"></p>
<p>分解后得到user矩阵和item矩阵的维度分别为nk和km，（k一般由用户指定），相比原来的rating矩阵，空间占用得到降低，并且分解后的user矩阵暗含着user偏好，Item矩阵暗含着item的属性，而user矩阵乘上item矩阵就是rating矩阵中用户对item的评分。因此，参考矩阵分解的过程，FM模型也将上式的二次项参数$w_{ij}$进行分解：  </p>
<p>$\hat{y}(x)=w_0+\sum_{i=1}^d  w_i  x_i  +\sum_{i=1}^d  \sum_{j=i+1}^d  &lt;v_i\cdot v_j&gt;  x_i  x_j$</p>
<p>其中$v_i$是第i维特征的隐向量，其长度为$k（k \ll d）$ 。$&lt;v_i \cdot v_j&gt;$为內积，其乘积为原来的$w_{ij}$，即 $\hat{w_{ij}}=&lt;v_i \cdot v_j&gt;=\sum_{f=1}^k v_{i,f} \cdot v_{j,f}$。</p>
<p>为了方便说明，考虑下面的数据集（实际中应该进行One-hot编码，但并不影响此处的说明）：<br><img src="20201210204630282.png" srcset="/walker_sue/img/loading.gif"></p>
<p>对于上面的训练集。没有（NBC，Adias）组合，因此，Poly2模型就无法学习到参数 $w_{NBC,Adias}$。而FM模型可以通过特征组合（NBC，Adias）、（EPSN，Adias）分别学习到向量$V_{NBC}$和$V_{Adias}$，这样使得在测试集中得以进行预测。</p>
<h4 id="1-2FM模型学习"><a href="#1-2FM模型学习" class="headerlink" title="1.2FM模型学习"></a>1.2FM模型学习</h4><p><img src="formula1.png" srcset="/walker_sue/img/loading.gif"></p>
<h4 id="1-3FM小结"><a href="#1-3FM小结" class="headerlink" title="1.3FM小结"></a>1.3FM小结</h4><p><strong>FM的优势</strong></p>
<ul>
<li>  FM降低了因数据稀疏，导致交叉项参数学习不充分的影响。直接用One-hot进行多项式建模，DataSet中没有出现的特征组合的权重是学不出来的，而FM是基于MF的思想或者是基于latent factor model的思想进行的‘曲线救国’：</li>
</ul>
<ol>
<li> 通过先学习每个特征的隐向量，然后通过隐向量之间的內积来刻画交互项的权重。</li>
<li> 一个特征组合的样本数一定比单特征的样本数少&lt;=&gt;直接学习交互项的特征一定比学习隐向量要难。而且学习隐向量可以避免因数据稀疏导致的学习不充分的缺点。</li>
</ol>
<ul>
<li>  FM提升了参数学习率，因为FM需要训练的参数更少，一般情况下，隐向量的维度都是比较短的，且肯定远小于直接学习交互项的参数个数。</li>
<li>  FM模型对稀疏数据有更好地学习能力，通过交互项可以学习特征之间的关联关系，并且保证了学习效率和预估能力。</li>
<li>  与其他模型相比，它的优势如下：</li>
</ul>
<ol>
<li> FM是一种比较灵活的模型，通过合适的特征变换方式，FM可以模拟二阶多项式核的SVM模型、MF模型、SVD++模型等；</li>
<li> 相比SVM的二阶多项式核而言，FM在样本稀疏的情况下是有优势的。而且，FM的训练/预测复杂度是线性的，而二项多项式核SVM需要计算核矩阵，核矩阵复杂度就是$N^2$</li>
<li> MF虽然可以用类似SVD++等方式来增强对交互特征的学习，但是最多只能加两个特征。而FM是可以对任意阶的所有交互项进行学习</li>
</ol>
<ul>
<li>FM模型行得通的一些巧妙性：<ul>
<li>  FM求解latent factor vector的套路，是基于MF的latent factor model方法来做。</li>
<li>  矩阵分解方法用在FM上，以缩减参数个数，处理数据稀疏带来的学习不足问题，还能做embedding;</li>
<li>  FM可以看做是MF的generalized版本，不仅能够利用普通的用户反馈信息，还能融合情景信息、社交信息等诸多影响个性化推荐的因素。</li>
</ul>
</li>
</ul>
<h3 id="2-FM和线性分类模型的区别"><a href="#2-FM和线性分类模型的区别" class="headerlink" title="2.FM和线性分类模型的区别"></a>2.FM和线性分类模型的区别</h3><h4 id="2-1-SVM和FM的区别"><a href="#2-1-SVM和FM的区别" class="headerlink" title="2.1 SVM和FM的区别"></a>2.1 SVM和FM的区别</h4><ul>
<li>  SVM的二元特征交叉参数是独立的，而FM的二元特征交叉参数是两个k维的向量$v_i,v_j$，交叉参数就不是独立的，而是相互影响的。</li>
<li>  FM可以在原始形式下进行优化学习，而基于kernel的非线性SVM通常需要在对偶形式下进行</li>
<li>  FM的模型预测是与训练样本独立，而SVM则与部分训练样本有关，即支持向量</li>
</ul>
<p>为什么线性SVM在和多项式SVM在稀疏条件下效果会比较差呢？线性SVM只有一维特征，不能挖掘深层次的组合特征，在实际预测中并没有很好的表现；而多项式SVM正如前面提到的，交叉的多个特征需要在训练集上共线才能被学习到，否则该对应的参数就位0，这对于测试集上的case而言这样的特征就失去了意义。因此，在稀疏条件下，SVM表现并不能让人满意。而FM不一样，通过向量化的交叉，可以学习到不同特征之间的交互，进行提取到更深层次的抽象意义。</p>
<h4 id="2-2-FM和LR的区别"><a href="#2-2-FM和LR的区别" class="headerlink" title="2.2 FM和LR的区别"></a>2.2 FM和LR的区别</h4><ul>
<li>  LR是从组合特征的角度去描述单特征之间的交互结合；FM实际上是从模型（latent factor model）的角度来做的。即FM中特征的交互是模型参数的一部分。</li>
<li>  FM能很大程度上避免了数据稀疏行造成参数估计不准确的影响。</li>
<li>FM是通过MF的思想，基于latent factor，来降低交叉项参数学习不充分的影响：<ul>
<li>  具体而言，两个交互项的参数学习，是基于K维的latent factor。</li>
<li>  每个特征的latent factor是通过它与其它(n-1)个特征的latent factor交互后进行学习的，这就大大降低了因稀疏带来的学习不足的问题。</li>
<li>  latent factor学习充分了，交互项两个latent factor之间的内积）也就学习充分了。</li>
<li>  即FM学习的交互项的参数是单特征的隐向量。</li>
</ul>
</li>
</ul>
<h3 id="3-FM和MF的区别"><a href="#3-FM和MF的区别" class="headerlink" title="3.FM和MF的区别"></a>3.FM和MF的区别</h3><p><img src="FM_vs_MF1.png" srcset="/walker_sue/img/loading.gif"><br><img src="FM_vs_MF2.png" srcset="/walker_sue/img/loading.gif"></p>
<h3 id="4-FFM"><a href="#4-FFM" class="headerlink" title="4.FFM"></a>4.FFM</h3><p><a target="_blank" rel="noopener" href="https://www.csie.ntu.edu.tw/~r01922136/slides/ffm.pdf">FFM</a>是NTU（国立台湾大学）的Yu-Chin Iuan（阮毓钦，现在在美国Criteo工作）与其它比赛队员，借鉴了来自Michael Jahrer的论文中的field概念提出了FM的升级版模型。<br>看看下面的数据集：<br><img src="20201211202647403.png" srcset="/walker_sue/img/loading.gif"></p>
<p>对于第一条数据来说，FM模型的二次项为： $w_{EPSN} \cdot w_{Nike}+w_{EPSN} \cdot w_{Male}+w_{Nike} \cdot w_{Male}$ 。每个特征只用一个隐向量来学习和其它特征的潜在影响。对于上面的例子中，Nike是广告主，Male是用户的性别，描述描述（EPSN，Nike）和（EPSN，Male）特征组合，FM模型都用同一个$w_{EPSN}$，而实际上，EPSN作为广告商，其对广告主和用户性别的潜在影响可能时不同的。</p>
<p>因此，Yu-Chin Juan借鉴Michael Jahrer的论文<a target="_blank" rel="noopener" href="https://www.semanticscholar.org/paper/KDD-Cup-2012-Track-2-:-Ensemble-of-Collaborative-%E2%80%94-T%C3%B6scher-Jahrer/05a8058916e7359e52eaee081e13194efdb21484?p2df">Ensemble of collaborative filtering and feature engineered models for click through rate prediction</a>，将field概念引入FM模型。</p>
<p>field是什么呢？即相同性质的特征放在一个field。比如EPSN、NBC都是属于广告商field的，Nike、Adidas都是属于广告主field，Male、Female都是属于性别field的。简单的说，同一个类别特征进行One-hot编码后生成的数值特征都可以放在同一个field中，比如最开始的例子中Day=26/11/15，Day=19/2/15可以放在同一个field中。如果是数值特征而非类别，可以直接作为一个field。</p>
<p>引入了field后，对于刚才的例子来说，二次项变为：<br><img src="20201211203852290.png" srcset="/walker_sue/img/loading.gif"></p>
<ul>
<li>  对于特征组合（EPSN，Nike）来说，其隐向量采用的是$w_{EPSN,A}$和 $w_{Nike,P}$ ，对于 $w_{EPSN,A}$这是因为Nike属于广告主（Advertiser）的field，而第二项$w_{Nike,P}$则是EPSN是广告商（Publisher）的field。</li>
<li>  对于特征组合（EPSN，Male）来说，$w_{EPSN,G}$是因为Male是用户性别(Gender)的field，而第二项 $w_{Male,P}$是因为EPSN是广告商(Publisher)的field。</li>
</ul>
<p>下面的图很好的表示了三个模型的区别：</p>
<h3 id="4-1FFM数学公式"><a href="#4-1FFM数学公式" class="headerlink" title="4.1FFM数学公式"></a>4.1FFM数学公式</h3><p>因此，FFM的数学公式表示为：<br>$y(x)=w_0+\sum_{i=1}^d w_i x_i+ \sum_{i=1}^d \sum_{j=i+1}^d(w_{i,f_j} \cdot (w_{j,f_i}) x_i x_j $</p>
<p>$f_i$和$f_j$分别代表第i个特征和第j个特征所属的field。若field有f个，隐向量的长度为k，则二次项系数共有dfk个，远多于FM模型的dk个。此外，隐向量和field相关，并不能像FM模型一样将二次项化简，计算的复杂度是$d^2k$。</p>
<p>通常情况下，每个隐向量只需要学习特定的field的表示，所以有$k_{FFM} \ll k_{FM}$。</p>
<h3 id="4-2FFM模型学习"><a href="#4-2FFM模型学习" class="headerlink" title="4.2FFM模型学习"></a>4.2FFM模型学习</h3><p><img src="formula2.png" srcset="/walker_sue/img/loading.gif"><br><img src="formula3.png" srcset="/walker_sue/img/loading.gif"><br><img src="formula4.png" srcset="/walker_sue/img/loading.gif"></p>
<p>这就是论文中算法1描述的过程：<br><img src="20201213205108340.png" srcset="/walker_sue/img/loading.gif"></p>
<p>在FFM原论文中，作者指出，FFM模型对于one-hot后类别特征十分有效，但是如果数据不够稀疏，可能相比其它模型提升没有稀疏的时候那么大，此外，对于数值型的数据效果不是特别的好。在Github上有<a target="_blank" rel="noopener" href="https://github.com/ycjuan/libffm">FFM</a>的开源实现，要使用FFM模型，特征需要转化为“field_id:feature_id:value”格式，相比LibSVM的格式多了field_id，即特征所属的field的编号，feature_id是特征编号，value为特征的值。</p>
<p>此外，我们需要关注的训练FFM时的一些注意事项：</p>
<ul>
<li>  样本归一化。FFM默认是进行样本数据的归一化的 。若不进行归一化，很容易造成数据inf溢出，进而引起梯度计算的nan错误。因此，样本层面的数据是推荐进行归一化的。</li>
<li>  特征归一化。CTR/CVR模型采用了多种类型的源特征，包括数值型和categorical类型等。但是，categorical类编码后的特征取值只有0或1，较大的数值型特征会造成样本归一化后categorical类生成特征的值非常小，没有区分性。例如，一条用户-商品记录，用户为“男”性，商品的销量是5000个（假设其它特征的值为零），那么归一化后特征“sex=male”（性别为男）的值略小于0002，而“volume”（销量）的值近似为1。特征“sex=male”在这个样本中的作用几乎可以忽略不计，这是相当不合理的。因此，将源数值型特征的值归一化到[0,1]是非常必要的。</li>
<li>  省略零值特征。从FFM模型的表达式可以看出，零值特征对模型完全没有贡献。包含零值特征的一次项和组合项均为零，对于训练模型参数或者目标值预估是没有作用的。因此，可以省去零值特征，提高FFM模型训练和预测的速度，这也是稀疏样本采用FFM的显著优势。</li>
</ul>
<h3 id="5-DeepFM"><a href="#5-DeepFM" class="headerlink" title="5.DeepFM"></a>5.DeepFM</h3><p>近年来深度学习模型在解决NLP、CV等领域的问题上取得了不错的效果，于是有学者将深度神经网络模型在与FM模型结合，提出了<a target="_blank" rel="noopener" href="https://ar$x_i$v.org/pdf/1703.04247.pdf">DeepFM模型</a>。FM通过对每一位特征的隐变量内积来提取特征组合，最后的结果也不错，虽然理论上FM可以对高阶特征组合进行建模，但实际上因为计算复杂度原因，一般都只用到了二阶特征组合。对于告诫特征组合来说，我们自然想到多层神经网络DNN。</p>
<h4 id="5-1FM结构"><a href="#5-1FM结构" class="headerlink" title="5.1FM结构"></a>5.1FM结构</h4><p><img src="20201213205820569.png" srcset="/walker_sue/img/loading.gif"></p>
<h4 id="5-2DNN结构"><a href="#5-2DNN结构" class="headerlink" title="5.2DNN结构"></a>5.2DNN结构</h4><p><img src="20201213205848210.png" srcset="/walker_sue/img/loading.gif"></p>
<h4 id="5-3DeepFM结构（FM和DNN的特征结合）"><a href="#5-3DeepFM结构（FM和DNN的特征结合）" class="headerlink" title="5.3DeepFM结构（FM和DNN的特征结合）"></a>5.3DeepFM结构（FM和DNN的特征结合）</h4><p><img src="20201213205911565.png" srcset="/walker_sue/img/loading.gif"></p>
<p>DeepFM的架构其实特别清晰：</p>
<ul>
<li>  输入的是稀疏特征的id</li>
<li>  进行一层lookup之后得到id的稠密embedding</li>
<li>  embedding一方面作为隐向量输入到FM层进行计算</li>
<li>  同时该embedding进行聚合之后输入到一个DNN模型(deep)</li>
<li>  然后将FM层和DNN层的输入求和之后进行co-train</li>
</ul>
<p>DeepFM目的是同时学习低阶和高阶特征交叉，主要由FM和DNN两部分组成，底部共享同样的输入。模型可以表示为：<br>$$\hat{y} = sigmoid(y_{FM} + y_{DNN}) $$</p>
<h4 id="5-4FM部分"><a href="#5-4FM部分" class="headerlink" title="5.4FM部分"></a>5.4FM部分</h4><p>原理如上，数学表达为：<br>$$y_{FM}=&lt;w,x&gt; + \sum_{i=1}^d \sum_{j=i+1}^d &lt;V_i,V_j&gt; x_i x_j$$</p>
<h4 id="5-5Deep部分"><a href="#5-5Deep部分" class="headerlink" title="5.5Deep部分"></a>5.5Deep部分</h4><p>深度部分是一个前馈神经网络，与图像或语音类的输入不同，CTR的输入一般是极其稀疏的，因此需要重新设计网络结构。在第一层隐藏层之前，引入一个嵌入层来完成输入向量压缩到低位稠密向量：<br><img src="2020121321041141.png" srcset="/walker_sue/img/loading.gif"></p>
<p>嵌入层的结构如上图所示，有两个有趣的特性：</p>
<ul>
<li>  尽管不同field的输入长度不同，但是embedding之后向量的长度均为k</li>
<li>  在FM中得到的隐变量Vik现在作为嵌入层网络的权重</li>
</ul>
<p>嵌入层的输出为$a^{(0)}=[e_1,e_2,…,e_m]$，其中$e_i$是嵌入的第i个field，m是field的个数，前向过程将嵌入层的输出输入到隐藏层为：<br>$$a^{(l+1)} = \sigma(W^{(l)}a^{(l)}+b^{(l)})$$</p>
<p>其中l是层数，$\sigma$是激活函数，$W^{(l)}$是模型的权重，$b^{(l)}$是 l层的偏置，因此，DNN的预测模型表达为：<br>$$ y_{DNN}=W^{|H|+1} \cdot a^{|H|}+b^{|H|+1} $$ </p>
<h4 id="5-6DeepFM模型对比"><a href="#5-6DeepFM模型对比" class="headerlink" title="5.6DeepFM模型对比"></a>5.6DeepFM模型对比</h4><p>目前在推荐领域中比较流行的深度模型有FNN、PNN、Wide&amp;Deep。</p>
<ul>
<li>  FNN模型是用FM模型来对Embedding层进行初始化的全连接神经网络。</li>
<li>  PNN模型则是在Embedding层和全连接层之间引入了内积/外积层，来学习特征之间的交互关系。</li>
<li>  Wide&amp;Deep模型由谷歌提出，将LR和DNN联合训练，在Google Play取得了线上效果的提升。Wide&amp;Deep模型，很大程度上满足了模型同时学习低阶特征和高阶特征的需求，让模型同时具备较好的“memorization”和“generalization”。但是需要人工特征工程来为Wide模型选取输入特征。具体而言，对哪些稀疏的特征进行embedding，是由人工指定的。</li>
</ul>
<p>有学者将DeepFM与当前流行的应用于CTR的神经网络做了对比：<img src="2020121321115840.png" srcset="/walker_sue/img/loading.gif"></p>
<p>从预训练，特征维度以及特征工程的角度进行对比，发现：<br><img src="20201213211242324.png" srcset="/walker_sue/img/loading.gif"></p>
<p>从实验效果来看，DeepFM的效果较好：<br><img src="2020121321125888.png" srcset="/walker_sue/img/loading.gif"></p>
<p>DeepFM的三大优势：</p>
<ul>
<li>  相对比于Wide&amp;Deep不再需要手工构建wide部分；</li>
<li>  相对比于FNN把FM的隐向量参数直接作为网络参数学习；</li>
<li>  DeepFM将embedding层结果输入给FM和MLP，两者输出叠加，达到捕捉了低阶和高阶特征交叉的目的。</li>
</ul>
<h3 id="6-NFM-Neural-Factorization-Machines"><a href="#6-NFM-Neural-Factorization-Machines" class="headerlink" title="6.NFM(Neural Factorization Machines)"></a>6.NFM(Neural Factorization Machines)</h3><p><a target="_blank" rel="noopener" href="https://github.com/he$x_i$angnan/neural_factorization_machine">NFM(Neural Factorization Machines)</a>又是在FM上的一个改进工作，出发点是FM通过隐向量可以对完成一个很好的特征组合工作，并且还解决了稀疏的问题，但是FM对于它对于non-linear和higher-order 特征交叉能力不足，而NFM则是结合了FM和NN来弥补这个不足。<br><img src="20201213211624104.png" srcset="/walker_sue/img/loading.gif"></p>
<p>DeepFM 是用 Wide &amp; Deep 框架，在 FM 旁边加了一个 NN，最后一并 sigmoid 输出。NFM 的做法则是利用隐向量逐项相乘得到的向量作为 MLP 的输入，构建的 FM + NN 模型。其中：</p>
<ul>
<li><p>  Input Feature Vector层是输入的稀疏向量，可以带权</p>
</li>
<li><p>  Embedding Layer对输入的稀疏向量look up 成稠密的embedding 向量</p>
</li>
<li><p>  Bi-Interaction Layer将每个特征embedding进行两两做element-wise product，Bi-Interaction的输出是一个 k维向量（就是隐向量的大小）,这层负责了特征之间second-order组合。$f_{Bi}(V_x)=\sum_i^n \sum_{j=j+1}^n x_i v_i \odot x_j v_j $类似FM的式子转换，这里同样可以做如下转换将复杂度降低：$f_{Bi}(V_x) = \frac{1}{2}[(\sum_i^n x_i v_i)^2-\sum_i^n(x_i v_i)^2]$ </p>
</li>
<li><p>Hidden Layers这里是多层学习高阶组合特征学习,其实就是一个DNN模块:<br>  <img src="https://img-blog.csdnimg.cn/20201213212136759.png" srcset="/walker_sue/img/loading.gif"></p>
</li>
<li><p>Prediction Score层就是输出最终的结果：<br>$y_{NFM}(x)=w_0+\sum_i^n w_i x_i +h^T \sigma L(W_l(…\sigma_1(w_1f_{Bi}(V_x)+b_1))+b_L) $</p>
</li>
</ul>
<p>FM可以看做是NFM模型 Hidden Layer层数为0一种特殊形式。最终的实验效果看来NFM也还是可以带来一个不错的效果：<br><img src="20201213212450566.png" srcset="/walker_sue/img/loading.gif"></p>
<h3 id="7-AFM-Attentional-Factorization-Machines"><a href="#7-AFM-Attentional-Factorization-Machines" class="headerlink" title="7.AFM(Attentional Factorization Machines)"></a>7.AFM(Attentional Factorization Machines)</h3><p><a target="_blank" rel="noopener" href="https://ar$x_i$v.org/pdf/1708.04617v1.pdf">AFM(Attentional Factorization Machines)</a>是浙大（Jun $x_i$ao, Hao Ye, Fei Wu）和新加坡国大（$x_i$angnan He, Hanwang Zhang, Tat-Seng Chua）几位同学提出来的模型。AFM 首先对 FM 做了神经网络改造，而后加入了注意力机制，为不同特征的二阶组合分配不同的权重。在传统的FM中进行特征组合时两两特征之间的组合都是等价的(只能通过隐向量的点积来区别)，这里趁着Attention的热度走一波，因为AFM的最大的贡献就是通过Attention建立权重矩阵来学习两两向量组合时不同的权重。下面就是AFM的框架图：</p>
<p>这里，$\alpha_{ij}$是通过注意力机制学习得到的特征i和特征j组合的权重，$\vec p$是对隐向量每个维度学习得到的权重，$\vec v_i \odot \vec v_j$表示向量 $\vec v_i$和 $\vec v_j$逐项相乘得到新向量。显然，当$\alpha_{ij}=1$且 $\vec p=\vec 1$，AFM退化为标准的FM模型。</p>
<p>其实整个算法思路也是很简单，但是在实验上却有一个不错的效果：<img src="20201213213624142.png" srcset="/walker_sue/img/loading.gif"></p>
<h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><p>1.<a target="_blank" rel="noopener" href="https://blog.csdn.net/yasin0/article/details/91349151">FFM及DeepFFM模型及其在推荐系统中的应用</a><br>2.<a target="_blank" rel="noopener" href="https://www.biaodianfu.com/ctr-fm-ffm-deepfm.html">CTR预估模型FM、FFM、DeepFM</a><br>3.<a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/149063040">推荐系统之FM与MF傻傻分不清楚</a></p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/walker_sue/categories/BI/">BI</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/categories/BI/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">机器学习</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/categories/BI/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95/">推荐算法</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/BI/">BI</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95/">推荐算法</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/FM/">FM</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/walker_sue/2021/07/31/week21-YouTube/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">CTR预估与Youtube推荐系统</span>
                        <span class="visible-mobile">Vorheriger</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/walker_sue/2021/07/09/week18-Apriori/">
                        <span class="hidden-mobile">挖掘数据中的关联规则</span>
                        <span class="visible-mobile">Nächster</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;TOC</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">Suchen</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">Stichwort</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/walker_sue/js/debouncer.js" ></script>
<script  src="/walker_sue/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/walker_sue/js/lazyload.js" ></script>
  



  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/walker_sue/js/clipboard-use.js" ></script>







  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '#post-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    function typing(id, title){
        var typed = new Typed('#' + id, {
            strings: [
              '  ',
              title + "&nbsp;",
            ],
            cursorChar: "_",
            typeSpeed: 70,
            loop: false,
        });
        typed.stop();
        $(document).ready(function () {
            $(".typed-cursor").addClass("h2");
            typed.start();
        });
    }
    
        typing("subtitle", "因子分解机, libFM与基于邻域的协同过滤")
    
  </script>


  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/walker_sue/js/local-search.js" ></script>
  <script>
    var path = "/walker_sue/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>





  

  
    <!-- MathJax -->
    <script>
      MathJax = {
        tex: {
          inlineMath: [['$', '$'], ['\\(', '\\)']]
        },
        options: {
          renderActions: {
            findScript: [10, doc => {
              document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
                const display = !!node.type.match(/; *mode=display/);
                const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
                const text = document.createTextNode('');
                node.parentNode.replaceChild(text, node);
                math.start = { node: text, delim: '', n: 0 };
                math.end = { node: text, delim: '', n: 0 };
                doc.math.push(math);
              });
            }, '', false],
            insertedScript: [200, () => {
              document.querySelectorAll('mjx-container').forEach(node => {
                let target = node.parentNode;
                if (target.nodeName.toLowerCase() === 'li') {
                  target.parentNode.classList.add('has-jax');
                }
              });
            }, '', false]
          }
        }
      };
    </script>

    <script async src="https://cdn.staticfile.org/mathjax/3.0.5/es5/tex-svg.js" ></script>

  











</body>
</html>
